package com.zunipe.until;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.zunipe.ZunipeTools;
import com.zunipe.minix.MinecraftClientMixin;
import com.zunipe.screen.ChangeNameScreen;
import com.zunipe.screen.OptionScreen;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.text.ClickEvent;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.JsonHelper;
import org.lwjgl.glfw.GLFW;

import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Iterator;
import java.util.TimeZone;

public class KeyBind
{
    private static final KeyBinding xray = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.xray",
            InputUtil.Type.KEYSYM,
            InputUtil.UNKNOWN_KEY.getCode(),
            "category.zunipetools.hotkey"
    ));
    private static final KeyBinding flower = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.flower",
            InputUtil.Type.KEYSYM,
            InputUtil.UNKNOWN_KEY.getCode(),
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding mine = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.mine",
            InputUtil.Type.KEYSYM,
            InputUtil.UNKNOWN_KEY.getCode(),
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding autoeat = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.autoeat",
            InputUtil.Type.KEYSYM,
            InputUtil.UNKNOWN_KEY.getCode(),
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding autoAttack = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.autoAttack",
            InputUtil.Type.KEYSYM,
            InputUtil.UNKNOWN_KEY.getCode(),
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding autoDrop = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.autoDrop",
            InputUtil.Type.KEYSYM,
            InputUtil.UNKNOWN_KEY.getCode(),
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding openOptionScreen = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.openOptionScreen",
            InputUtil.Type.KEYSYM,
            GLFW.GLFW_KEY_K,
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding openNightvision = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.openNightvision",
            InputUtil.Type.KEYSYM,
            GLFW.GLFW_KEY_J,
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding scanningBox = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.scanningBox",
            InputUtil.Type.KEYSYM,
            GLFW.GLFW_KEY_B,
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding backwardWalk = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.backwardWalk",
            InputUtil.Type.KEYSYM,
            GLFW.GLFW_KEY_O,
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding autoClickLeft = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.autoClickLeft",
            InputUtil.Type.KEYSYM,
            InputUtil.UNKNOWN_KEY.getCode(),
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding autoClickRight = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.autoClickRight",
            InputUtil.Type.KEYSYM,
            InputUtil.UNKNOWN_KEY.getCode(),
            "category.zunipetools.hotkey"
    ));

    private static final KeyBinding autoSignIn = KeyBindingHelper.registerKeyBinding(new KeyBinding(
            "key.zunipetools.autoSignIn",
            InputUtil.Type.KEYSYM,
            InputUtil.UNKNOWN_KEY.getCode(),
            "category.zunipetools.hotkey"
    ));

    public KeyBind()
    {
        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (autoSignIn.wasPressed())
            {
                SignInFunction.SignIn(client);
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (autoClickLeft.wasPressed())
            {
                if (client.player != null)
                {
                    Util.autoClickLeft = !Util.autoClickLeft;
                    if (Util.autoClickLeft)
                    {
                        client.player.sendMessage(new LiteralText("§l左键连点 §2§l开启"), true);
                        new Thread(() ->
                        {
                            while (Util.autoClickLeft)
                            {
                                try
                                {
                                    ((MinecraftClientMixin) client).doAttackInvoker();
                                    Thread.sleep(Util.clickLeftInterval);
                                } catch (ClassCastException | InterruptedException e)
                                {
                                    ZunipeTools.LOGGER.error(e.getMessage());
                                }
                            }
                        }).start();
                    }
                    else
                    {
                        client.player.sendMessage(new LiteralText("§l左键连点 §4§l关闭"), true);
                    }
                }
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (autoClickRight.wasPressed())
            {
                if (client.player != null)
                {
                    Util.autoClickRight = !Util.autoClickRight;
                    if (Util.autoClickRight)
                    {
                        client.player.sendMessage(new LiteralText("§l右键连点 §2§l开启"), true);
                        new Thread(() ->
                        {
                            while (Util.autoClickRight)
                            {
                                try
                                {

                                    client.options.keyUse.setPressed(true);
                                    Thread.sleep(75);
                                    client.options.keyUse.setPressed(false);
                                    Thread.sleep(Util.clickRightInterval);
                                } catch (InterruptedException e)
                                {
                                    ZunipeTools.LOGGER.error(e.getMessage());
                                }
                            }
                        }).start();
                    }
                    else
                    {
                        client.player.sendMessage(new LiteralText("§l右键连点 §4§l关闭"), true);
                    }
                }
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (backwardWalk.wasPressed())
            {
                if (client.player != null)
                {
                    Util.alwaysBackwardWalk = !Util.alwaysBackwardWalk;
                    if (Util.alwaysBackwardWalk)
                    {
                        client.player.sendMessage(new LiteralText("§l后退 §2§l开启"), true);
                        Thread t = new Thread(() ->
                        {
                            while (Util.alwaysBackwardWalk)
                            {
                                if (!client.options.keyBack.wasPressed())
                                    client.options.keyBack.setPressed(true);
                                try
                                {
                                    Thread.sleep(1000);
                                } catch (InterruptedException e)
                                {
                                    ZunipeTools.LOGGER.error(e.getMessage());
                                }
                            }
                        });
                        t.start();
                    }
                    else
                    {
                        client.player.sendMessage(new LiteralText("§l后退 §4§l关闭"), true);
                        client.options.keyBack.setPressed(false);
                    }
                }
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (scanningBox.wasPressed())
            {
                ScanningBoxFunction.ScanningBox(client);
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (openNightvision.wasPressed())
            {
                if (client.player == null)
                    continue;
                if (Util.openNightVision)
                {
                    Util.openNightVision = false;
                    client.player.sendMessage(new LiteralText("§l夜视 §4§l关闭"), true);
                }
                else
                {
                    Util.openNightVision = true;
                    client.player.sendMessage(new LiteralText("§l夜视 §2§l开启"), true);
                }
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (mine.wasPressed())
            {
                client.player.sendMessage(new LiteralText("[Zunipe] 物品列表"), false);
                for (Iterator<String> it = Util.itemList.stream().iterator(); it.hasNext(); )
                {
                    String name = it.next();
                    client.player.sendMessage(new LiteralText(name), false);
                }
                client.player.sendMessage(new LiteralText("[Zunipe] 排除列表"), false);
                for (Iterator<String> it = Util.exclusionItemList.stream().iterator(); it.hasNext(); )
                {
                    String name = it.next();
                    client.player.sendMessage(new LiteralText(name), false);
                }
                SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                client.player.sendMessage(new LiteralText("[Zunipe] 当前时间 " + s.format(new Date())), false);
                client.player.sendMessage(Text.of("[Zunipe] 时区 " + TimeZone.getDefault().getDisplayName()), false);

                if (client.player.getMainHandStack().isOf(Items.PLAYER_HEAD))
                {
                    ItemStack itemStack = client.player.getMainHandStack();
                    if (itemStack.hasNbt())
                    {
                        NbtCompound nbt = itemStack.getNbt();
                        String base64 = nbt.getCompound("SkullOwner").getCompound("Properties").getList("textures", NbtList.COMPOUND_TYPE).getCompound(0).getString("Value");
                        Base64.Decoder decoder = Base64.getDecoder();
                        String deString = new String(decoder.decode(base64));
                        JsonParser jsonParser = new JsonParser();
                        JsonObject jsonObject = jsonParser.parse(deString).getAsJsonObject();
                        JsonObject textures = JsonHelper.getObject(jsonObject, "textures");
                        JsonObject skin = JsonHelper.getObject(textures, "SKIN");
                        String url = JsonHelper.getString(skin, "url");
                        client.player.sendMessage(new LiteralText(url).setStyle(Style.EMPTY.withColor(Formatting.BLUE).withUnderline(true).withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url))), false);
                    }
                }
                client.setScreen(new ChangeNameScreen(client.currentScreen));
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (autoAttack.wasPressed())
            {
                AutoAttackFunction.AutoAttack(client);
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (autoDrop.wasPressed())
            {
                if (client.player == null)
                    return;
                if (Util.autoDrop)
                {
                    client.player.sendMessage(new LiteralText("§l自动丢弃手中物品 §4§l关闭"), true);
                    Util.autoDrop = false;
                }
                else
                {
                    client.player.sendMessage(new LiteralText("§l自动丢弃手中物品 §2§l开启"), true);
                    Util.autoDrop = true;
                    new Thread(() ->
                    {
                        while (Util.autoDrop)
                        {
                            client.player.dropSelectedItem(true);
                            try
                            {
                                Thread.sleep(100);
                            } catch (InterruptedException e)
                            {
                                throw new RuntimeException(e);
                            }
                        }
                    }).start();
                }
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (xray.wasPressed())
            {
                XrayFunction.XrayFunction(client);
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (openOptionScreen.wasPressed())
            {
                client.setScreen(new OptionScreen(client.currentScreen));
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (autoeat.wasPressed())
            {
                AutoEatFunction.AutoEat(client);
            }
        });

        ClientTickEvents.END_CLIENT_TICK.register(client ->
        {
            while (flower.wasPressed())
            {
                FlowerFunction.Flower(client);
            }
        });
    }
}
